<!--
 * @Author: fcli
 * @Date: 2023-09-04 10:34:58
 * @LastEditors: fcli
 * @LastEditTime: 2023-11-03 18:10:07
 * @FilePath: /vue-text-overflow/src/plugin/index.vue
 * @Description: vue文本超出提示组件(兼容h5和pc)
-->

<template>
    <div class="text-overflow-content">
        <input type="checkbox" v-model="selectVal" class="exp" :id="key" v-show="false">
        <div class="text" ref="textContent" :style="{ '--bottom': bottom, '-webkit-line-clamp': lineNumTemp,'max-height':maxHeight }">
            <label class="btn" ref="optBtn" :for="key" v-show="showExport && showExpBtn"></label>
            <slot></slot>
        </div>
        <div ref="tooltipRef" id="tooltip" class="tooltip" v-show="showOverflowTooltip && tooltipShow">
            <slot></slot>
            <div id="arrow" data-popper-arrow></div>
        </div>
    </div>
</template>
<script setup lang="ts">
import { ref, onMounted,watch } from 'vue';
import { createPopper } from '@popperjs/core';
const props=defineProps({
    //超过多少行省略
    lineNum: {
        default: 3,
        type: Number
    },
    showOverflowTooltip:{
        type: Boolean,
        default:false
    },
    showExport:{
        type: Boolean,
        default:true
    }
})
const key=ref('id'+Date.now());
const selectVal=ref(false);
const optBtn = ref<any>(null);
const textContent = ref<any>(null);
const tooltipRef = ref<any>(null);
const bottom = ref('-22px');
const showExpBtn = ref(false);
const tooltipShow = ref(false);
const maxHeight=ref('');
const lineNumTemp=ref(0)
watch(()=>selectVal.value,(e)=>{
    console.log(e)
    if(e){
        lineNumTemp.value=999
        /*设置一个足够大的行数就可以了*/
        maxHeight.value='none'
    }else{
        lineNumTemp.value=props.lineNum;
    }
})

onMounted(() => {
    lineNumTemp.value=props.lineNum;
    getBtnHeight();
    const mutation = new MutationObserver(handleShowExp);
    const config = {
        attributes: true,
        characterData: true,
        childList: true,
        subtree: true,
        attributeOldValue: true,
        characterDataOldValue: true
    }
    mutation.observe(textContent.value, config);
})
//处理计算是否展示展开和收起按钮
const handleShowExp = () => {
    if (textContent.value.scrollHeight > textContent.value.clientHeight) {
        showExpBtn.value = true;
        getBtnHeight();
    }
}

const getBtnHeight = () => {
    //计算展开/收起按钮的高度，动态改变
    const offsetHeight = optBtn.value.offsetHeight - 2
    bottom.value = `-${offsetHeight}px`
    handelTooltip();
}


//处理tooltip事件
const handelTooltip = () => {

    const button: any = textContent.value;
    const tooltip: any = tooltipRef.value;

    const popperInstance = createPopper(button, tooltip, {
        placement: 'top',
        modifiers: [
            {
                name: 'offset',
                options: {
                    offset: [0, 8],
                },
            },
        ],
    });

    function show() {
        // Make the tooltip visible
        tooltipShow.value = true;

        // Enable the event listeners
        popperInstance?.setOptions((options) => ({
            ...options,
            modifiers: [
                ...options.modifiers,
                { name: 'eventListeners', enabled: true },
            ],
        }));

        // Update its position
        popperInstance.update();
    }

    function hide() {
        tooltipShow.value = false;

        // Disable the event listeners
        popperInstance.setOptions((options) => ({
            ...options,
            modifiers: [
                ...options.modifiers,
                { name: 'eventListeners', enabled: false },
            ],
        }));
    }

    const showEvents = ['mouseenter', 'focus'];
    const hideEvents = ['mouseleave', 'blur'];

    showEvents.forEach((event) => {
        button.addEventListener(event, show);
    });

    hideEvents.forEach((event) => {
        button.addEventListener(event, hide);
    });
}



</script>
<style scoped>
.text-overflow-content {
    display: flex;
}

#arrow,
#arrow::before {
    position: absolute;
    width: 8px;
    height: 8px;
    background: inherit;
}

#arrow {
    visibility: hidden;
}

#arrow::before {
    visibility: visible;
    content: '';
    transform: rotate(45deg);
}

#tooltip[data-popper-placement^='top']>#arrow {
    bottom: -4px;
}

#tooltip[data-popper-placement^='bottom']>#arrow {
    top: -4px;
}

#tooltip[data-popper-placement^='left']>#arrow {
    right: -4px;
}

#tooltip[data-popper-placement^='right']>#arrow {
    left: -4px;
}

.tooltip {
    background: #333;
    color: #fff;
    border-radius: 4px;
    font-size: 14px;
    padding: 4px 8px;
    max-width: 300px;
}

.text {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    transition: .3s max-height;

}



.exp:checked+.text .btn::after {
    content: '收起'
}

.exp:checked+.text .btn::before {
    visibility: hidden;
    /*在展开状态下隐藏省略号*/
}

.btn::after {
    content: '展开'
}


.text::before {
    content: '';
    float: right;
    width: 0;
    height: 100%;
    margin-bottom: var(--bottom);
}

.btn {
    margin-right: 12px;
    float: right;
    clear: both;
    cursor: pointer;
    color: #377ef9;
}
</style>

